From 76105d8a76f6d2c1ee64089e5694f4a947bebfbb Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Wed, 25 May 2005 08:42:25 +0000 Subject: [PATCH] bitkeeper revision 1.1542.1.1 (42943a71LGhR_dI1LOX6lKtJ08zzTA) setup.py, Makefile: Remove XenSV -- it's been broken since twisted was removed. Many files: Delete: tools/misc/xensv Delete: tools/python/xen/sv/params.py Delete: tools/python/xen/sv/__init__.py Delete: tools/python/xen/sv/MigrateDomain.py Delete: tools/python/xen/sv/Daemon.py Delete: tools/python/xen/sv/util.py Delete: tools/python/xen/sv/Wizard.py Delete: tools/python/xen/sv/TabView.py Delete: tools/python/xen/sv/SaveDomain.py Delete: tools/python/xen/sv/RestoreDomain.py Delete: tools/python/xen/sv/NodeInfo.py Delete: tools/python/xen/sv/Main.py Delete: tools/python/xen/sv/HTMLBase.py Delete: tools/python/xen/sv/GenTabbed.py Delete: tools/python/xen/sv/DomList.py Delete: tools/python/xen/sv/DomInfo.py Delete: tools/python/xen/sv/CreateDomain.py Delete: tools/sv/images/unpause.png Delete: tools/sv/images/small-unpause.png Delete: tools/sv/images/small-pause.png Delete: tools/sv/images/small-destroy.png Delete: tools/sv/images/shutdown.png Delete: tools/sv/images/seperator.jpg Delete: tools/sv/images/right-end-highlight.jpg Delete: tools/sv/images/reboot.png Delete: tools/sv/images/previous.png Delete: tools/sv/images/pause.png Delete: tools/sv/images/orb_02.jpg Delete: tools/sv/images/next.png Delete: tools/sv/images/middle-no-highlight.jpg Delete: tools/sv/images/middle-highlight.jpg Delete: tools/sv/images/left-end-no-highlight.jpg Delete: tools/sv/images/left-end-highlight.jpg Delete: tools/sv/images/finish.png Delete: tools/sv/images/destroy.png Delete: tools/sv/inc/style.css Delete: tools/sv/images/seperator-right-highlight.jpg Delete: tools/sv/images/seperator-left-highlight.jpg Delete: tools/sv/inc/script.js Delete: tools/sv/images/right-end-no-highlight.jpg Delete: tools/sv/images/orb_01.jpg Delete: tools/sv/Makefile Delete: tools/sv/Main.rpy Signed-off-by: Christian Limpach --- .rootkeys | 44 --- tools/misc/Makefile | 2 +- tools/misc/xensv | 137 --------- tools/python/setup.py | 1 - tools/python/xen/sv/CreateDomain.py | 163 ----------- tools/python/xen/sv/Daemon.py | 108 ------- tools/python/xen/sv/DomInfo.py | 149 ---------- tools/python/xen/sv/DomList.py | 81 ------ tools/python/xen/sv/GenTabbed.py | 131 --------- tools/python/xen/sv/HTMLBase.py | 63 ---- tools/python/xen/sv/Main.py | 113 -------- tools/python/xen/sv/MigrateDomain.py | 72 ----- tools/python/xen/sv/NodeInfo.py | 64 ----- tools/python/xen/sv/RestoreDomain.py | 46 --- tools/python/xen/sv/SaveDomain.py | 59 ---- tools/python/xen/sv/TabView.py | 49 ---- tools/python/xen/sv/Wizard.py | 269 ------------------ tools/python/xen/sv/__init__.py | 1 - tools/python/xen/sv/params.py | 3 - tools/python/xen/sv/util.py | 123 -------- tools/sv/Main.rpy | 3 - tools/sv/Makefile | 34 --- tools/sv/images/destroy.png | Bin 2408 -> 0 bytes tools/sv/images/finish.png | Bin 1189 -> 0 bytes tools/sv/images/left-end-highlight.jpg | Bin 535 -> 0 bytes tools/sv/images/left-end-no-highlight.jpg | Bin 440 -> 0 bytes tools/sv/images/middle-highlight.jpg | Bin 376 -> 0 bytes tools/sv/images/middle-no-highlight.jpg | Bin 344 -> 0 bytes tools/sv/images/next.png | Bin 1270 -> 0 bytes tools/sv/images/orb_01.jpg | Bin 19864 -> 0 bytes tools/sv/images/orb_02.jpg | Bin 507 -> 0 bytes tools/sv/images/pause.png | Bin 1662 -> 0 bytes tools/sv/images/previous.png | Bin 1285 -> 0 bytes tools/sv/images/reboot.png | Bin 3132 -> 0 bytes tools/sv/images/right-end-highlight.jpg | Bin 535 -> 0 bytes tools/sv/images/right-end-no-highlight.jpg | Bin 447 -> 0 bytes tools/sv/images/seperator-left-highlight.jpg | Bin 552 -> 0 bytes tools/sv/images/seperator-right-highlight.jpg | Bin 560 -> 0 bytes tools/sv/images/seperator.jpg | Bin 443 -> 0 bytes tools/sv/images/shutdown.png | Bin 2901 -> 0 bytes tools/sv/images/small-destroy.png | Bin 483 -> 0 bytes tools/sv/images/small-pause.png | Bin 434 -> 0 bytes tools/sv/images/small-unpause.png | Bin 500 -> 0 bytes tools/sv/images/unpause.png | Bin 1890 -> 0 bytes tools/sv/images/xen.png | Bin 10575 -> 0 bytes tools/sv/inc/script.js | 22 -- tools/sv/inc/style.css | 32 --- 47 files changed, 1 insertion(+), 1768 deletions(-) delete mode 100755 tools/misc/xensv delete mode 100644 tools/python/xen/sv/CreateDomain.py delete mode 100644 tools/python/xen/sv/Daemon.py delete mode 100755 tools/python/xen/sv/DomInfo.py delete mode 100755 tools/python/xen/sv/DomList.py delete mode 100755 tools/python/xen/sv/GenTabbed.py delete mode 100755 tools/python/xen/sv/HTMLBase.py delete mode 100755 tools/python/xen/sv/Main.py delete mode 100644 tools/python/xen/sv/MigrateDomain.py delete mode 100755 tools/python/xen/sv/NodeInfo.py delete mode 100644 tools/python/xen/sv/RestoreDomain.py delete mode 100644 tools/python/xen/sv/SaveDomain.py delete mode 100755 tools/python/xen/sv/TabView.py delete mode 100755 tools/python/xen/sv/Wizard.py delete mode 100755 tools/python/xen/sv/__init__.py delete mode 100644 tools/python/xen/sv/params.py delete mode 100755 tools/python/xen/sv/util.py delete mode 100755 tools/sv/Main.rpy delete mode 100755 tools/sv/Makefile delete mode 100644 tools/sv/images/destroy.png delete mode 100644 tools/sv/images/finish.png delete mode 100644 tools/sv/images/left-end-highlight.jpg delete mode 100644 tools/sv/images/left-end-no-highlight.jpg delete mode 100644 tools/sv/images/middle-highlight.jpg delete mode 100644 tools/sv/images/middle-no-highlight.jpg delete mode 100644 tools/sv/images/next.png delete mode 100755 tools/sv/images/orb_01.jpg delete mode 100755 tools/sv/images/orb_02.jpg delete mode 100644 tools/sv/images/pause.png delete mode 100644 tools/sv/images/previous.png delete mode 100755 tools/sv/images/reboot.png delete mode 100644 tools/sv/images/right-end-highlight.jpg delete mode 100644 tools/sv/images/right-end-no-highlight.jpg delete mode 100644 tools/sv/images/seperator-left-highlight.jpg delete mode 100644 tools/sv/images/seperator-right-highlight.jpg delete mode 100644 tools/sv/images/seperator.jpg delete mode 100755 tools/sv/images/shutdown.png delete mode 100644 tools/sv/images/small-destroy.png delete mode 100644 tools/sv/images/small-pause.png delete mode 100644 tools/sv/images/small-unpause.png delete mode 100644 tools/sv/images/unpause.png delete mode 100644 tools/sv/images/xen.png delete mode 100755 tools/sv/inc/script.js delete mode 100644 tools/sv/inc/style.css diff --git a/.rootkeys b/.rootkeys index 1891b6afe9..ac98ede4db 100644 --- a/.rootkeys +++ b/.rootkeys @@ -731,7 +731,6 @@ 405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons 40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend 41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/misc/xenperf.c -4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv 4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops 40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm 4270cc81g3nSNYCZ1ryCMDEbLtMtbQ tools/pygrub/Makefile @@ -802,22 +801,6 @@ 3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/python/xen/lowlevel/xc/xc.c 40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/python/xen/lowlevel/xu/__init__.py 40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/lowlevel/xu/xu.c -41052eb84_irpx0E9N_kqBp9eoin5g tools/python/xen/sv/CreateDomain.py -4107986egkTAMIHW7n-i4ShvCGWpLQ tools/python/xen/sv/Daemon.py -40fcefb2qm13BbRZBydAatOavaS0fQ tools/python/xen/sv/DomInfo.py -40fcefb2-RIU8GB67mJMRzybME9bxw tools/python/xen/sv/DomList.py -40fcefb23FfQn-ZBCbcHqA0cPGqQxw tools/python/xen/sv/GenTabbed.py -40fcefb2QZAn3u3sX-M7NXBjOv5HGg tools/python/xen/sv/HTMLBase.py -40fcefb2vnfDbl4w_yCTedROPuqs0g tools/python/xen/sv/Main.py -4186e24fZMp7_bX4f50MvUscdrST9Q tools/python/xen/sv/MigrateDomain.py -40fcefb24h-04WaHag-Tg4nxWPhTig tools/python/xen/sv/NodeInfo.py -4186e24fb4YtJw155tNtSXXN6nEWqA tools/python/xen/sv/RestoreDomain.py -4186e24fVXt0lfeQSAy1eiFKnPCHTg tools/python/xen/sv/SaveDomain.py -40fcefb2Sif__6AqrANeBQZZfvP-6w tools/python/xen/sv/TabView.py -41052eb8UrgtUkuJPg7oY1tutVQHsg tools/python/xen/sv/Wizard.py -40fcefb2DqteqCCZYDCvvh4Q5jBd0w tools/python/xen/sv/__init__.py -4107986e6qN1IdvIDdId0AYFmDMkiQ tools/python/xen/sv/params.py -40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/sv/util.py 40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py 40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py 4270e4efFg3wHCCxXpA0h6yoMTkeSQ tools/python/xen/util/blkif.py @@ -893,33 +876,6 @@ 40cf2937PSslwBliN1g7ofDy2H_RhA tools/python/xen/xm/opts.py 40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/python/xen/xm/shutdown.py 41b88ba6_C4---jeA895Efg9YFZgKA tools/python/xen/xm/sysrq.py -40fcefb2K1xqVVT4D-p7nL2GzS4scg tools/sv/Main.rpy -40ffbcb66Dj5F-1kCK9BcgSqCWkt1w tools/sv/Makefile -4120b0e5L_nW-u0MWRfIdXg4ng4OjA tools/sv/images/destroy.png -4107c921_OR9NTSv2dKFiLCXxrXoxA tools/sv/images/finish.png -40fcefb3wXQMsl9WkgQAVtdrupm4sw tools/sv/images/left-end-highlight.jpg -40fcefb3K6ESt5sQhD9aCQRscQIlXQ tools/sv/images/left-end-no-highlight.jpg -40fcefb3BUT98zPzW8kAFKuxGdh4XA tools/sv/images/middle-highlight.jpg -40fcefb38OTgsUKHBpwshLLIsiIaCA tools/sv/images/middle-no-highlight.jpg -41052eb9SDUqSLGtG6rxk6Ep5fOhFA tools/sv/images/next.png -40fcefb32SPtrw36c4S6YGFlLvkKuw tools/sv/images/orb_01.jpg -40fcefb3Ok5qkX3iM7ZEPVkRInrUpg tools/sv/images/orb_02.jpg -4104ffca9_GhWOxRE-83uZIad2Z1gg tools/sv/images/pause.png -41052eb9NQqHe_f9-ev1CaA3y5YYZg tools/sv/images/previous.png -41013a82ILk71xLqWFH5ZO5VmOIvBw tools/sv/images/reboot.png -40fcefb3JnT5XeKTuVF4yUMGOtuNZg tools/sv/images/right-end-highlight.jpg -40fcefb3-DuYOS7noo2W7b_0p7TOUg tools/sv/images/right-end-no-highlight.jpg -40fcefb3qNbAZR5FYGPAZ9sFPVMTDA tools/sv/images/seperator-left-highlight.jpg -40fcefb3dgsa24WLk_BJeYQHrDLuOg tools/sv/images/seperator-right-highlight.jpg -40fcefb3FtiX4Pd2kT8wDlp8u8xRhQ tools/sv/images/seperator.jpg -41013a82sUdUqBv8EoAUJii3gsZ-4g tools/sv/images/shutdown.png -4120b0e5RyNoIQNMjUs4A2kshovjaQ tools/sv/images/small-destroy.png -4120b0e6vW66wW6WvjQyFD0AZH2tng tools/sv/images/small-pause.png -4120b0e6USof7ieyGxEvtCdTMpxaQw tools/sv/images/small-unpause.png -4104ffca-jPHLVOrW0n0VghEXXtKxg tools/sv/images/unpause.png -40fcefb3yMSrZvApO9ToIi-iQwnchA tools/sv/images/xen.png -41013a83z27rKvWIxAfUBMVZ1eDCDg tools/sv/inc/script.js -40fcefb3zGC9XNBkSwTEobCoq8YClA tools/sv/inc/style.css 422f27c8MDeRoOWZNdcRC5VDTcj3TQ tools/tests/Makefile 422f27c81CCtXt4Lthf7JF3Ajr0fUA tools/tests/test_x86_emulator.c 420b963dK3yGNtqxRM8npGZtrCQd1g tools/vnet/00INSTALL diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 5281e94e00..5eebbfda12 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -16,7 +16,7 @@ HDRS = $(wildcard *.h) TARGETS = xenperf xc_shadow INSTALL_BIN = $(TARGETS) xencons -INSTALL_SBIN = netfix xm xend xensv xenperf +INSTALL_SBIN = netfix xm xend xenperf all: build build: $(TARGETS) diff --git a/tools/misc/xensv b/tools/misc/xensv deleted file mode 100755 index 339ed66a93..0000000000 --- a/tools/misc/xensv +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env python -# -*- mode: python; -*- -#============================================================================ -# Copyright (C) 2004 Tom Wilkie -# Copyright (C) 2004 Mike Wray -#============================================================================ - -"""SV web interface Lives in /usr/sbin. - Provides pretty HTML management interface. - - Run: - - sv start - - The daemon is stopped with: - - sv stop - - The daemon will be accessible from http://localhost:8080/ -""" -import os -import sys -import re - -# add fallback path for non-native python path installs if needed -sys.path.append('/usr/lib/python') -sys.path.append('/usr/lib64/python') -from xen.xend.server.params import XEND_PID_FILE - -class CheckError(ValueError): - pass - -def hline(): - print >>sys.stderr, "*" * 70 - -def msg(message): - print >>sys.stderr, "*" * 3, message - -def check_logging(): - """Check python logging is installed and raise an error if not. - Logging is standard from Python 2.3 on. - """ - try: - import logging - except ImportError: - hline() - msg("Python logging is not installed.") - msg("Use 'make install-logging' at the xen root to install.") - msg("") - msg("Alternatively download and install from") - msg("http://www.red-dove.com/python_logging.html") - hline() - raise CheckError("logging is not installed") - -def check_twisted_version(): - """Check twisted is installed with a supported version and print a warning if not. - Raises an error if twisted is not installed. - """ - # Supported twisted release and major version. - RELEASE = 1 - MAJOR = 3 - try: - from twisted.copyright import version - except ImportError: - hline() - msg("The Twisted framework is not installed.") - msg("Use 'make install-twisted' at the xen root to install.") - msg("") - msg("Alternatively download and install version %d.%d or higher" % (RELEASE, MAJOR)) - msg("from http://www.twistedmatrix.com/products") - hline() - raise CheckError("twisted is not installed") - - - (release, major, minor) = version.split('.') - release = int(release) - major = int(major) - if release > RELEASE: return - if release == RELEASE and major >= MAJOR: return - hline() - msg("Warning: Twisted version not supported: %s" % version) - msg("Use Twisted version %d.%d.0 or higher" % (RELEASE, MAJOR)) - hline() - -def check_xend(): - """Check xend is running - """ - - if not os.path.isfile(XEND_PID_FILE) or not os.path.getsize(XEND_PID_FILE): - hline() - msg( "Warning: Xend has not been detected as running." ) - msg( "Please start it immediately with: xend start " ) - hline() - return 0 - - # Read the pid of the previous invocation and search active process list. - pid = open(XEND_PID_FILE, 'r').read() - lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines() - for line in lines: - if re.search('^ *' + pid + '.+xend', line): - return 1 - - hline() - msg( "Warning: Xend has not been detected as running." ) - msg( "Please start it immediately with: xend start " ) - hline() - return 0 - -def main(): - try: - check_logging() - check_twisted_version() - check_xend() - except CheckError: - sys.exit(1) - - from xen.sv import Daemon - - daemon = Daemon.instance() - - if not sys.argv[1:]: - print 'usage: %s {start|stop|restart}' % sys.argv[0] - elif os.fork(): - pid, status = os.wait() - return status >> 8 - elif sys.argv[1] == 'start': - return daemon.start() - elif sys.argv[1] == 'stop': - return daemon.stop() - elif sys.argv[1] == 'restart': - return daemon.stop() or daemon.start() - else: - print 'not an option:', sys.argv[1] - return 1 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/python/setup.py b/tools/python/setup.py index 76861908a6..e6b04f8708 100644 --- a/tools/python/setup.py +++ b/tools/python/setup.py @@ -39,7 +39,6 @@ setup(name = 'xen', 'xen.util', 'xen.xend', 'xen.xend.server', - 'xen.sv', 'xen.xm', 'xen.web', ], diff --git a/tools/python/xen/sv/CreateDomain.py b/tools/python/xen/sv/CreateDomain.py deleted file mode 100644 index 4378897e5c..0000000000 --- a/tools/python/xen/sv/CreateDomain.py +++ /dev/null @@ -1,163 +0,0 @@ -from xen.sv.Wizard import * -from xen.sv.util import * -from xen.sv.GenTabbed import PreTab - -from xen.xm.create import make_config, OptVals - -from xen.xend.XendClient import server - -class CreateDomain( Wizard ): - def __init__( self, urlWriter ): - - sheets = [ CreatePage0, - CreatePage1, - CreatePage2, - CreatePage3, - CreatePage4, - CreateFinish ] - - Wizard.__init__( self, urlWriter, "Create Domain", sheets ) - -class CreatePage0( Sheet ): - - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "General", 0 ) - self.addControl( InputControl( 'name', 'VM Name', 'VM Name:', "[\\w|\\S]+", "You must enter a name in this field" ) ) - self.addControl( InputControl( 'memory', '64', 'Memory (Mb):', "[\\d]+", "You must enter a number in this field" ) ) - self.addControl( InputControl( 'cpu', '0', 'CPU:', "[\\d]+", "You must enter a number in this feild" ) ) - self.addControl( InputControl( 'cpu_weight', '1', 'CPU Weight:', "[\\d]+", "You must enter a number in this feild" ) ) - -class CreatePage1( Sheet ): - - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "Setup Kernel Image", 1 ) -# For now we don't need to select a builder... -# self.addControl( ListControl( 'builder', [('linux', 'Linux'), ('netbsd', 'NetBSD')], 'Kernel Type:' ) ) - self.addControl( FileControl( 'kernel', '/boot/vmlinuz-2.6.9-xenU', 'Kernel Image:' ) ) - self.addControl( InputControl( 'extra', '', 'Kernel Command Line Parameters:' ) ) - -class CreatePage2( Sheet ): - - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 2 ) - self.addControl( InputControl( 'num_vbds', '1', 'Number of VBDs:', '[\\d]+', "You must enter a number in this field" ) ) - -class CreatePage3( Sheet ): - - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 3 ) - - def write_BODY( self, request, err ): - if not self.passback: self.parseForm( request ) - - previous_values = sxp2hash( string2sxp( self.passback ) ) #get the hash for quick reference - - num_vbds = previous_values.get( 'num_vbds' ) - - for i in range( int( num_vbds ) ): - self.addControl( InputControl( 'vbd%s_dom0' % i, 'phy:sda%s' % str(i + 1), 'Device %s name:' % i ) ) - self.addControl( InputControl( 'vbd%s_domU' % i, 'sda%s' % str(i + 1), 'Virtualized device %s:' % i ) ) - self.addControl( ListControl( 'vbd%s_mode' % i, [('w', 'Read + Write'), ('r', 'Read Only')], 'Device %s mode:' % i ) ) - - self.addControl( InputControl( 'root', '/dev/sda1', 'Root device (in VM):' ) ) - - Sheet.write_BODY( self, request, err ) - -class CreatePage4( Sheet ): - - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "Network settings", 4 ) - self.addControl( ListControl( 'dhcp', [('off', 'No'), ('dhcp', 'Yes')], 'Use DHCP:' ) ) - self.addControl( InputControl( 'hostname', 'hostname', 'VM Hostname:' ) ) - self.addControl( InputControl( 'ip_addr', '1.2.3.4', 'VM IP Address:' ) ) - self.addControl( InputControl( 'ip_subnet', '255.255.255.0', 'VM Subnet Mask:' ) ) - self.addControl( InputControl( 'ip_gateway', '1.2.3.4', 'VM Gateway:' ) ) - self.addControl( InputControl( 'ip_nfs', '1.2.3.4', 'NFS Server:' ) ) - -class CreateFinish( Sheet ): - - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "All Done", 5 ) - - def write_BODY( self, request, err ): - - if not self.passback: self.parseForm( request ) - - xend_sxp = self.translate_sxp( string2sxp( self.passback ) ) - - try: - dom_sxp = server.xend_domain_create( xend_sxp ) - success = "Your domain was successfully created.\n" - except: - success = "There was an error creating your domain.\nThe configuration used is as follows:\n" - dom_sxp = xend_sxp - - - - pt = PreTab( success + sxp2prettystring( dom_sxp ) ) - pt.write_BODY( request ) - - request.write( "

" % self.passback ) - request.write( "

" % self.location ) - - def translate_sxp( self, fin_sxp ): - fin_hash = ssxp2hash( fin_sxp ) - - def get( key ): - ret = fin_hash.get( key ) - if ret: - return ret - else: - return "" - - vals = OptVals() - - vals.name = get( 'name' ) - vals.memory = get( 'memory' ) - vals.maxmem = get( 'maxmem' ) - vals.cpu = get( 'cpu' ) - vals.cpu_weight = get( 'cpu_weight' ) - - vals.builder = get( 'builder' ) - vals.kernel = get( 'kernel' ) - vals.root = get( 'root' ) - vals.extra = get( 'extra' ) - - #setup vbds - - vbds = [] - - for i in range( int( get( 'num_vbds' ) ) ): - vbds.append( ( get( 'vbd%s_dom0' % i ), get('vbd%s_domU' % i ), get( 'vbd%s_mode' % i ) ) ) - - vals.disk = vbds - - #misc - - vals.pci = [] - - vals.blkif = None - vals.netif = None - vals.restart = None - vals.console = None - vals.ramdisk = None - - #setup vifs - - vals.vif = [] - vals.nics = 1 - - ip = get( 'ip_addr' ) - nfs = get( 'ip_nfs' ) - gate = get( 'ip_gateway' ) - mask = get( 'ip_subnet' ) - host = get( 'hostname' ) - dhcp = get( 'dhcp' ) - - vals.cmdline_ip = "%s:%s:%s:%s:%s:eth0:%s" % (ip, nfs, gate, mask, host, dhcp) - - try: - return make_config( vals ) - except: - return [["Error creating domain config."]] - diff --git a/tools/python/xen/sv/Daemon.py b/tools/python/xen/sv/Daemon.py deleted file mode 100644 index 510cfa9f04..0000000000 --- a/tools/python/xen/sv/Daemon.py +++ /dev/null @@ -1,108 +0,0 @@ -########################################################### -## XenSV Web Control Interface Daemon -## Copyright (C) 2004, K A Fraser (University of Cambridge) -## Copyright (C) 2004, Mike Wray -## Copyright (C) 2004, Tom Wilkie -########################################################### - -import os -import os.path -import sys -import re - -from xen.sv.params import * - -from twisted.internet import reactor -from twisted.web import static, server, script - -class Daemon: - """The xend daemon. - """ - def __init__(self): - self.shutdown = 0 - self.traceon = 0 - - def daemon_pids(self): - pids = [] - pidex = '(?P\d+)' - pythonex = '(?P\S*python\S*)' - cmdex = '(?P.*)' - procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$') - xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$') - procs = os.popen('ps -e -o pid,args 2>/dev/null') - for proc in procs: - pm = procre.match(proc) - if not pm: continue - xm = xendre.match(pm.group('cmd')) - if not xm: continue - #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd') - pids.append(int(pm.group('pid'))) - return pids - - def new_cleanup(self, kill=0): - err = 0 - pids = self.daemon_pids() - if kill: - for pid in pids: - print "Killing daemon pid=%d" % pid - os.kill(pid, signal.SIGHUP) - elif pids: - err = 1 - print "Daemon already running: ", pids - return err - - def cleanup(self, kill=False): - # No cleanup to do if PID_FILE is empty. - if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE): - return 0 - # Read the pid of the previous invocation and search active process list. - pid = open(PID_FILE, 'r').read() - lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines() - for line in lines: - if re.search('^ *' + pid + '.+xensv', line): - if not kill: - print "Daemon is already running (pid %d)" % int(pid) - return 1 - # Old daemon is still active: terminate it. - os.kill(int(pid), 1) - # Delete the stale PID_FILE. - os.remove(PID_FILE) - return 0 - - def start(self, trace=0): - if self.cleanup(kill=False): - return 1 - - # Fork -- parent writes PID_FILE and exits. - pid = os.fork() - if pid: - # Parent - pidfile = open(PID_FILE, 'w') - pidfile.write(str(pid)) - pidfile.close() - return 0 - # Child - self.run() - return 0 - - def stop(self): - return self.cleanup(kill=True) - - def run(self): - root = static.File( SV_ROOT ) - root.indexNames = [ 'Main.rpy' ] - root.processors = { '.rpy': script.ResourceScript } - reactor.listenTCP( SV_PORT, server.Site( root ) ) - reactor.run() - - def exit(self): - reactor.disconnectAll() - sys.exit(0) - -def instance(): - global inst - try: - inst - except: - inst = Daemon() - return inst diff --git a/tools/python/xen/sv/DomInfo.py b/tools/python/xen/sv/DomInfo.py deleted file mode 100755 index 8aabb19057..0000000000 --- a/tools/python/xen/sv/DomInfo.py +++ /dev/null @@ -1,149 +0,0 @@ -from xen.xend.XendClient import getAsynchServer -server = getAsynchServer() -from xen.xend import PrettyPrint - -from xen.sv.HTMLBase import HTMLBase -from xen.sv.util import * -from xen.sv.GenTabbed import * - -DEBUG=1 - -class DomInfo( GenTabbed ): - - def __init__( self, urlWriter ): - - self.dom = 0; - - def tabUrlWriter( tab ): - return urlWriter( "&dom=%s%s" % ( self.dom, tab ) ) - - GenTabbed.__init__( self, "Domain Info", tabUrlWriter, [ 'General', 'SXP', 'Devices' ], [ DomGeneralTab, DomSXPTab, NullTab ] ) - - def write_BODY( self, request ): - dom = request.args.get('dom') - - if dom is None or len(dom) != 1: - request.write( "

Please Select a Domain

" ) - return None - else: - self.dom = dom[0] - - GenTabbed.write_BODY( self, request ) - - def write_MENU( self, request ): - pass - -class DomGeneralTab( CompositeTab ): - def __init__( self ): - CompositeTab.__init__( self, [ DomGenTab, DomActionTab ] ) - -class DomGenTab( GeneralTab ): - - def __init__( self ): - - titles = {} - - titles[ 'ID' ] = 'dom' - titles[ 'Name' ] = 'name' - titles[ 'CPU' ] = 'cpu' - titles[ 'Memory' ] = ( 'mem', memoryFormatter ) - titles[ 'State' ] = ( 'state', stateFormatter ) - titles[ 'Total CPU' ] = ( 'cpu_time', smallTimeFormatter ) - titles[ 'Up Time' ] = ( 'up_time', bigTimeFormatter ) - - GeneralTab.__init__( self, {}, titles ) - - def write_BODY( self, request ): - - self.dom = getVar('dom', request) - - if self.dom is None: - request.write( "

Please Select a Domain

" ) - return None - - self.dict = getDomInfoHash( self.dom ) - - GeneralTab.write_BODY( self, request ) - -class DomSXPTab( PreTab ): - - def __init__( self ): - self.dom = 0 - PreTab.__init__( self, "" ) - - - def write_BODY( self, request ): - self.dom = getVar('dom', request) - - if self.dom is None: - request.write( "

Please Select a Domain

" ) - return None - - try: - domInfo = server.xend_domain( self.dom ) - except: - domInfo = [["Error getting domain details."]] - - self.source = sxp2prettystring( domInfo ) - - PreTab.write_BODY( self, request ) - -class DomActionTab( ActionTab ): - - def __init__( self ): - actions = { "shutdown" : ( "Shutdown the Domain", "shutdown.png" ), - "reboot" : ( "Reboot the Domain", "reboot.png" ), - "pause" : ( "Pause the Domain", "pause.png" ), - "unpause" : ( "Unpause the Domain", "unpause.png" ), - "destroy" : ( "Destroy the Domain", "destroy.png" ) } - ActionTab.__init__( self, actions ) - - def op_shutdown( self, request ): - dom = getVar( 'dom', request ) - if not dom is None and dom != '0': - if DEBUG: print ">DomShutDown %s" % dom - try: - server.xend_domain_shutdown( int( dom ), "halt" ) - except: - pass - - def op_reboot( self, request ): - dom = getVar( 'dom', request ) - if not dom is None and dom != '0': - if DEBUG: print ">DomReboot %s" % dom - try: - server.xend_domain_shutdown( int( dom ), "reboot" ) - except: - pass - - def op_pause( self, request ): - dom = getVar( 'dom', request ) - if not dom is None and dom != '0': - if DEBUG: print ">DomPause %s" % dom - try: - server.xend_domain_pause( int( dom ) ) - except: - pass - - def op_unpause( self, request ): - dom = getVar( 'dom', request ) - if not dom is None and dom != '0': - if DEBUG: print ">DomUnpause %s" % dom - try: - server.xend_domain_unpause( int( dom ) ) - except: - pass - - def op_destroy( self, request ): - dom = getVar( 'dom', request ) - if not dom is None and dom != '0': - if DEBUG: print ">DomDestroy %s" % dom - try: - server.xend_domain_destroy( int( dom ), "halt" ) - except: - pass - - - - - diff --git a/tools/python/xen/sv/DomList.py b/tools/python/xen/sv/DomList.py deleted file mode 100755 index 86976b7af3..0000000000 --- a/tools/python/xen/sv/DomList.py +++ /dev/null @@ -1,81 +0,0 @@ -from xen.xend.XendClient import server -from xen.xend import sxp - -from xen.sv.HTMLBase import HTMLBase -from xen.sv.util import * - -class DomList( HTMLBase ): - - isLeaf = True - - def __init__( self, urlWriter ): - HTMLBase.__init__(self) - self.urlWriter = urlWriter - - def write_MENU( self, request ): - return self.write_BODY( request, head=True, long=False ) - - def write_BODY( self, request, head=True, long=True ): - - domains = None - - try: - domains = server.xend_domains() - domains.sort() - except: - pass - - request.write( "\n\n" ) - - if head: - request.write( "" ) - self.write_DOMAIN_HEAD( request, long ) - request.write( "" ) - - odd = True - - if not domains is None: - for domain in domains: - if odd: - request.write( "\n" ) - odd = False - else: - request.write( "\n" ) - odd = True - self.write_DOMAIN( request, getDomInfoHash( domain ), long ) - request.write( "\n" ) - else: - request.write( "

Error getting domain list
Perhaps XenD not running?

") - - request.write( "
\n" ) - - def write_DOMAIN( self, request, domInfoHash, long=True ): - request.write( "%(id)s\n" % domInfoHash ) - - url = self.urlWriter( "&mod=info&dom=%(id)s" % domInfoHash ) - - request.write( "%s\n" % ( url, domInfoHash['name'] ) ) - if long: - request.write( "%(memory)5s\n" % domInfoHash ) - request.write( "%(cpu)2s\n" % domInfoHash ) - request.write( "%(state)5s\n" % domInfoHash ) - if domInfoHash[ 'id' ] != "0": - request.write( "" ) - - if domInfoHash[ 'state' ][ 2 ] == "-": - request.write( "" % domInfoHash ) - else: - request.write( "" % domInfoHash ) - - request.write( "" % domInfoHash) - else: - request.write( " " ) - - def write_DOMAIN_HEAD( self, request, long=True ): - request.write( "Domain\n" ) - request.write( "Name\n" ) - if long: - request.write( "Memory / Mb\n" ) - request.write( "CPU\n" ) - request.write( "State\n" ) - request.write( "\n" ) diff --git a/tools/python/xen/sv/GenTabbed.py b/tools/python/xen/sv/GenTabbed.py deleted file mode 100755 index aef1848e7a..0000000000 --- a/tools/python/xen/sv/GenTabbed.py +++ /dev/null @@ -1,131 +0,0 @@ -import types - -from xen.sv.HTMLBase import HTMLBase -from xen.sv.TabView import TabView -from xen.sv.util import getVar - -class GenTabbed( HTMLBase ): - - def __init__( self, title, urlWriter, tabStrings, tabObjects ): - HTMLBase.__init__(self) - self.tabStrings = tabStrings - self.tabObjects = tabObjects - self.urlWriter = urlWriter - self.title = title - - def write_BODY( self, request, urlWriter = None ): - - tab = int( getVar( 'tab', request, 0 ) ) - - request.write( "" ) - request.write( "
" ) - - request.write( "

%s

" % self.title ) - - TabView( tab, self.tabStrings, self.urlWriter ).write_BODY( request ) - - request.write( "
" ) - - render_tab = self.tabObjects[ tab ] - - if render_tab is None: - request.write( "

Bad Tab

" ) - self.finish_BODY( request ) - else: - render_tab().write_BODY( request ) - - request.write( "
" ) - - def perform( self, request ): - tab = int( getVar( 'tab', request, 0 ) ) - - op_tab = self.tabObjects[ tab ] - - if op_tab: - op_tab().perform( request ) - -class PreTab( HTMLBase ): - - def __init__( self, source ): - HTMLBase.__init__( self ) - self.source = source - - def write_BODY( self, request ): - - request.write( "
" )
-        
-        request.write( self.source )
-        
-        request.write( "
" ) - -class GeneralTab( HTMLBase ): - - def __init__( self, dict, titles ): - HTMLBase.__init__( self ) - self.dict = dict - self.titles = titles - - def write_BODY( self, request ): - - request.write( "" ) - - def writeAttr( niceName, attr, formatter=None ): - if type( attr ) is types.TupleType: - ( attr, formatter ) = attr - - if attr in self.dict: - if formatter: - temp = formatter( self.dict[ attr ] ) - else: - temp = str( self.dict[ attr ] ) - request.write( "" % ( niceName, temp ) ) - - for niceName, attr in self.titles.items(): - writeAttr( niceName, attr ) - - request.write( "

%s:

%s

" ) - -class NullTab( HTMLBase ): - - def __init__( self ): - HTMLBase.__init__( self ) - self.title = "Null Tab" - - def write_BODY( self, request ): - request.write( "

%s

" % self.title ) - -class ActionTab( HTMLBase ): - - def __init__( self, actions ): - self.actions = actions - HTMLBase.__init__( self ) - - def write_BODY( self, request ): - request.write("

") - - for ( command, ( text, image ) ) in self.actions.items(): - request.write("") - request.write("  ") - - request.write("

 

") - request.write("

") - -class CompositeTab( HTMLBase ): - - def __init__( self, tabs ): - HTMLBase.__init__( self ) - self.tabs = tabs - - def write_BODY( self, request ): - for tab in self.tabs: - request.write( "
" ) - tab().write_BODY( request ) - - def perform( self, request ): - for tab in self.tabs: - tab().perform( request ) - - - - diff --git a/tools/python/xen/sv/HTMLBase.py b/tools/python/xen/sv/HTMLBase.py deleted file mode 100755 index e67784d558..0000000000 --- a/tools/python/xen/sv/HTMLBase.py +++ /dev/null @@ -1,63 +0,0 @@ -from twisted.web.resource import Resource -from xen.sv.util import * - -class HTMLBase( Resource ): - - isLeaf = True - - def __init__( self ): - Resource.__init__(self) - - def render_POST( self, request ): - self.perform( request ) - return self.render_GET( request ) - - def render_GET( self, request ): - self.write_TOP( request ) - self.write_BODY( request ) - self.write_BOTTOM( request ) - return '' - - def write_BODY( self, request ): - request.write( "BODY" ) - - def write_TOP( self, request ): - request.write( 'Xen' ) - request.write( '' ) - request.write( '' ) - request.write('
' % request.uri) - - def write_BOTTOM( self, request ): - request.write('') - request.write('') - request.write('
') - request.write( "" ) - - def get_op_method(self, op): - """Get the method for an operation. - For operation 'foo' looks for 'op_foo'. - - op operation name - returns method or None - """ - op_method_name = 'op_' + op - return getattr(self, op_method_name, None) - - def perform(self, req): - """General operation handler for posted operations. - For operation 'foo' looks for a method op_foo and calls - it with op_foo(req). Replies with code 500 if op_foo - is not found. - - The method must return a list when req.use_sxp is true - and an HTML string otherwise (or list). - Methods may also return a Deferred (for incomplete processing). - - req request - """ - op = req.args.get('op') - if not op is None and len(op) == 1: - op = op[0] - op_method = self.get_op_method(op) - if op_method: - op_method( req ) diff --git a/tools/python/xen/sv/Main.py b/tools/python/xen/sv/Main.py deleted file mode 100755 index 196e1c1450..0000000000 --- a/tools/python/xen/sv/Main.py +++ /dev/null @@ -1,113 +0,0 @@ -from xen.sv.HTMLBase import HTMLBase -from xen.sv.DomList import DomList -from xen.sv.NodeInfo import NodeInfo -from xen.sv.DomInfo import DomInfo -from xen.sv.CreateDomain import CreateDomain -from xen.sv.MigrateDomain import MigrateDomain -from xen.sv.SaveDomain import SaveDomain -from xen.sv.RestoreDomain import RestoreDomain - -from xen.xend.XendClient import server - -from xen.sv.util import getVar - -class Main( HTMLBase ): - - isLeaf = True - - def __init__( self, urlWriter = None ): - self.modules = { "node": NodeInfo, - "list": DomList, - "info": DomInfo, - "create": CreateDomain, - "migrate" : MigrateDomain, - "save" : SaveDomain, - "restore" : RestoreDomain } - - # ordered list of module menus to display - self.module_menus = [ "node", "create", "migrate", "save", - "restore", "list" ] - HTMLBase.__init__(self) - - def render_POST( self, request ): - - #decide what module post'd the action - - args = getVar( 'args', request ) - - mod = getVar( 'mod', request ) - - if not mod is None and args is None: - module = self.modules[ mod ] - #check module exists - if module: - module( self.mainUrlWriter ).perform( request ) - else: - self.perform( request ) - - return self.render_GET( request ) - - def mainUrlWriter( self, module ): - def fun( f ): - return "Main.rpy?mod=%s%s" % ( module, f ) - return fun - - def write_BODY( self, request ): - - request.write( "\n\n" ) - request.write( "\n" ) - request.write( " " ) - request.write( " \n" ) - request.write( " " ) - request.write( " \n" ) - request.write( " " ) - request.write( "\n" ) - - request.write( "
 " ) - request.write( " " ) - request.write( " " ) - request.write( " ") - request.write( " " ) - request.write( "
" ) - request.write( "

SV Web Interface
(C) Tom Wilkie 2004

" ) - - for modName in self.module_menus: - self.modules[modName]( self.mainUrlWriter( modName ) ).write_MENU( request ) - - request.write( "
" ) - request.write( "  " ) - request.write( "
 " ) - request.write( " " ) - request.write( " " ) - request.write( " " ) - request.write( "
" ) - - modName = getVar('mod', request) - - if modName is None: - request.write( '

Please select a module

' ) - else: - module = self.modules[ modName ] - if module: - module( self.mainUrlWriter( modName ) ).write_BODY( request ) - else: - request.write( '

Invalid module. Please select another

' ) - - request.write( "
" ) - request.write( "
 
\n" ) - - - def op_destroy( self, request ): - dom = getVar( 'dom', request ) - if not dom is None and dom != "0": - server.xend_domain_destroy( int( dom ), "halt" ) - - def op_pause( self, request ): - dom = getVar( 'dom', request ) - if not dom is None and dom != "0": - server.xend_domain_pause( int( dom ) ) - - def op_unpause( self, request ): - dom = getVar( 'dom', request ) - if not dom is None and dom != "0": - server.xend_domain_unpause( int( dom ) ) diff --git a/tools/python/xen/sv/MigrateDomain.py b/tools/python/xen/sv/MigrateDomain.py deleted file mode 100644 index 928acf3f42..0000000000 --- a/tools/python/xen/sv/MigrateDomain.py +++ /dev/null @@ -1,72 +0,0 @@ -from xen.sv.Wizard import * -from xen.sv.util import * -from xen.sv.GenTabbed import PreTab - -from xen.xm.create import make_config, OptVals - -from xen.xend.XendClient import server - -class MigrateDomain( Wizard ): - def __init__( self, urlWriter ): - - sheets = [ ChooseMigrateDomain, - DoMigrate ] - - Wizard.__init__( self, urlWriter, "Migrate Domain", sheets ) - - -class ChooseMigrateDomain( Sheet ): - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "Configure Migration", 0) - try: - domains = server.xend_domains() - domains.sort() - except: - pass - - domnames = [] - for i in domains: - if i != 'Domain-0': domnames.append((i,i)) - - self.addControl( ListControl('domid', - domnames, - 'Domain ID:') ) - self.addControl( TickControl('live', - 'True', - 'Live migrate:') ) - self.addControl( InputControl('rate', - '0', - 'Rate limit:') ) - self.addControl( InputControl( 'dest', 'myhost.mydomain', - 'Name or IP address:', - ".*") ) - -class DoMigrate( Sheet ): - def __init__(self, urlWriter ): - Sheet.__init__(self, urlWriter, "Migration Done", 1) - - def write_BODY( self, request, err ): - - if not self.passback: self.parseForm( request ) - -# print string2sxp(self.passback) - - config = ssxp2hash ( string2sxp( self.passback ) ) - - try: - print config - print config['domid'], config['dest'] - dom_sxp = server.xend_domain_migrate( config['domid'], - config['dest'], - config.get('live') == 'True', - config['rate'] ) - success = "Your domain was successfully Migrated.\n" - except Exception, e: - success = "There was an error migrating your domain\n" - dom_sxp = str(e) - - pt = PreTab( success + dom_sxp ) # sxp2prettystring( dom_sxp ) ) - pt.write_BODY( request ) - - request.write( "

" % self.passback ) - request.write( "

" % self.location ) diff --git a/tools/python/xen/sv/NodeInfo.py b/tools/python/xen/sv/NodeInfo.py deleted file mode 100755 index 5db1a34c50..0000000000 --- a/tools/python/xen/sv/NodeInfo.py +++ /dev/null @@ -1,64 +0,0 @@ -from xen.xend.XendClient import server - -from xen.sv.util import * -from xen.sv.GenTabbed import * - -class NodeInfo( GenTabbed ): - - def __init__( self, urlWriter ): - - GenTabbed.__init__( self, "Node Details", urlWriter, [ 'General', 'Dmesg', ], [ NodeGeneralTab, NodeDmesgTab ] ) - - def write_MENU( self, request ): - request.write( "

Node details

" % self.urlWriter( '' ) ) - -class NodeGeneralTab( CompositeTab ): - def __init__( self ): - CompositeTab.__init__( self, [ NodeInfoTab, NodeActionTab ] ) - -class NodeInfoTab( GeneralTab ): - - def __init__( self ): - - nodeInfo = {} - try: - nodeInfo = sxp2hash( server.xend_node() ) - except: - nodeInfo[ 'system' ] = 'Error getting node info' - - dictTitles = {} - dictTitles[ 'System' ] = 'system' - dictTitles[ 'Hostname' ] = 'host' - dictTitles[ 'Release' ] = 'release' - dictTitles[ 'Version' ] ='version' - dictTitles[ 'Machine' ] = 'machine' - dictTitles[ 'Cores' ] = 'cores' - dictTitles[ 'Hyperthreading' ] = ( 'hyperthreads_per_core', hyperthreadFormatter ) - dictTitles[ 'CPU Speed' ] = ( 'cpu_mhz', cpuFormatter ) - dictTitles[ 'Memory' ] = ( 'memory', memoryFormatter ) - dictTitles[ 'Free Memory' ] = ( 'free_memory', memoryFormatter ) - - GeneralTab.__init__( self, dict=nodeInfo, titles=dictTitles ) - -class NodeDmesgTab( PreTab ): - - def __init__( self ): - try: - dmesg = server.xend_node_get_dmesg() - except: - dmesg = "Error getting node information: XenD not running?" - PreTab.__init__( self, dmesg ) - -class NodeActionTab( ActionTab ): - - def __init__( self ): - ActionTab.__init__( self, { "shutdown" : ( "Shutdown the Node", "shutdown.png" ), - "reboot" : ( "Reboot the Node", "reboot.png" ) } ) - - def op_shutdown( self, request ): - print ">NodeShutDown" - server.xend_node_shutdown() - - def op_reboot( self, request ): - print ">NodeReboot" - server.xend_node_reboot() diff --git a/tools/python/xen/sv/RestoreDomain.py b/tools/python/xen/sv/RestoreDomain.py deleted file mode 100644 index be8b4f558a..0000000000 --- a/tools/python/xen/sv/RestoreDomain.py +++ /dev/null @@ -1,46 +0,0 @@ -from xen.sv.Wizard import * -from xen.sv.util import * -from xen.sv.GenTabbed import PreTab - -from xen.xm.create import make_config, OptVals - -from xen.xend.XendClient import server - -class RestoreDomain( Wizard ): - def __init__( self, urlWriter ): - - sheets = [ ChooseRestoreDomain, - DoRestore ] - - Wizard.__init__( self, urlWriter, "Restore Domain", sheets ) - - -class ChooseRestoreDomain( Sheet ): - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "Configure Restore", 0) - - self.addControl( InputControl( 'file', '', - 'Suspend file name:', - ".*") ) - -class DoRestore( Sheet ): - def __init__(self, urlWriter ): - Sheet.__init__(self, urlWriter, "Restore Done", 1) - - def write_BODY( self, request, err ): - - if not self.passback: self.parseForm( request ) - config = ssxp2hash ( string2sxp( self.passback ) ) - - try: - dom_sxp = server.xend_domain_restore( config['file'] ) - success = "Your domain was successfully restored.\n" - except Exception, e: - success = "There was an error restoring your domain\n" - dom_sxp = str(e) - - pt = PreTab( success + sxp2prettystring( dom_sxp ) ) - pt.write_BODY( request ) - - request.write( "

" % self.passback ) - request.write( "

" % self.location ) diff --git a/tools/python/xen/sv/SaveDomain.py b/tools/python/xen/sv/SaveDomain.py deleted file mode 100644 index 4c4e315272..0000000000 --- a/tools/python/xen/sv/SaveDomain.py +++ /dev/null @@ -1,59 +0,0 @@ -from xen.sv.Wizard import * -from xen.sv.util import * -from xen.sv.GenTabbed import PreTab - -from xen.xm.create import make_config, OptVals - -from xen.xend.XendClient import server - -class SaveDomain( Wizard ): - def __init__( self, urlWriter ): - - sheets = [ ChooseSaveDomain, - DoSave ] - - Wizard.__init__( self, urlWriter, "Save Domain", sheets ) - - -class ChooseSaveDomain( Sheet ): - def __init__( self, urlWriter ): - Sheet.__init__( self, urlWriter, "Configure Save", 0) - try: - domains = server.xend_domains() - domains.sort() - except: - pass - - domnames = [] - for i in domains: - if i != 'Domain-0': domnames.append((i,i)) - - self.addControl( ListControl('domid', - domnames, - 'Domain ID:') ) - self.addControl( InputControl( 'file', '', - 'Suspend file name:', - ".*") ) - -class DoSave( Sheet ): - def __init__(self, urlWriter ): - Sheet.__init__(self, urlWriter, "Save Done", 1) - - def write_BODY( self, request, err ): - - if not self.passback: self.parseForm( request ) - config = ssxp2hash ( string2sxp( self.passback ) ) - - try: - dom_sxp = server.xend_domain_save( config['domid'], - config['file'] ) - success = "Your domain was successfully saved.\n" - except Exception, e: - success = "There was an error saving your domain\n" - dom_sxp = str(e) - - pt = PreTab( success + dom_sxp ) # sxp2prettystring( dom_sxp ) ) - pt.write_BODY( request ) - - request.write( "

" % self.passback ) - request.write( "

" % self.location ) diff --git a/tools/python/xen/sv/TabView.py b/tools/python/xen/sv/TabView.py deleted file mode 100755 index cada51c4e8..0000000000 --- a/tools/python/xen/sv/TabView.py +++ /dev/null @@ -1,49 +0,0 @@ -from xen.sv.HTMLBase import HTMLBase - -class TabView( HTMLBase ): - - def __init__( self, tab, tabs, urlWriter ): - HTMLBase.__init__(self) - self.tab = tab # interger - tab id - self.tabs = tabs - self.urlWriter = urlWriter - - def write_BODY( self, request ): - request.write( "" ) - request.write( "" ) - - if self.tab == 0: - image = "left-end-highlight.jpg" - else: - image = "left-end-no-highlight.jpg" - - request.write( "" % image ) - - count = len( self.tabs ) - - for i in range( count ): - - if i == self.tab: - image = "middle-highlight.jpg" - else: - image = "middle-no-highlight.jpg" - - request.write( "" % ( image, self.urlWriter( "&tab=%s" % i ), self.tabs[ i ] ) ) - - if i < count-1: - if i == self.tab: - image = "seperator-left-highlight.jpg" - elif self.tab == i+1: - image = "seperator-right-highlight.jpg" - else: - image = "seperator.jpg" - - request.write( "" % image ) - - if self.tab == count - 1: - image = "right-end-highlight.jpg" - else: - image = "right-end-no-highlight.jpg" - - request.write( "" % image ) - request.write( "

%s

" ) diff --git a/tools/python/xen/sv/Wizard.py b/tools/python/xen/sv/Wizard.py deleted file mode 100755 index 089d3f2e67..0000000000 --- a/tools/python/xen/sv/Wizard.py +++ /dev/null @@ -1,269 +0,0 @@ -from xen.sv.util import * -from xen.sv.HTMLBase import HTMLBase -from xen.xend import sxp - -import re - -DEBUG = 0 - -class Wizard( HTMLBase ): - - def __init__( self, urlWriter, title, sheets ): - HTMLBase.__init__( self ) - self.title = title - self.sheets = sheets - self.urlWriter = urlWriter - - def write_MENU( self, request ): - request.write( "

%s

" % (self.urlWriter( '' ), self.title) ) - - def write_BODY( self, request ): - - request.write( "
" ) - request.write( "

%s

" % self.title ) - - currSheet = getVar( 'sheet', request ) - - if not currSheet is None: - currSheet = int( currSheet ) - else: - currSheet = 0 - - sheet = self.sheets[ currSheet ]( self.urlWriter ) - - err = not sheet.validate( request ) - - if not err: - op = getVar( 'op', request ) - - if op == 'next': - currSheet += 1 - elif op == 'prev': - currSheet -= 1 - - sheet = self.sheets[ currSheet ]( self.urlWriter ) - - if getVar( 'visited-sheet%s' % currSheet, request ): - sheet.write_BODY( request, err ) - else: - sheet.write_BODY( request, False ) - - - request.write( "
" ) - request.write( "

" ) - if currSheet > 0: - request.write( " " ) - if currSheet < ( len( self.sheets ) - 2 ): - request.write( "" ) - elif currSheet == ( len( self.sheets ) - 2 ): - request.write( "" ) - request.write( "

" ) - request.write( "
" ) - - def op_next( self, request ): - pass - - def op_prev( self, request ): - pass - - def op_finish( self, request ): - pass - -class Sheet( HTMLBase ): - - def __init__( self, urlWriter, title, location ): - HTMLBase.__init__( self ) - self.urlWriter = urlWriter - self.feilds = [] - self.title = title - self.location = location - self.passback = None - - def parseForm( self, request ): - do_not_parse = [ 'mod', 'op', 'sheet', 'passback' ] - - passed_back = request.args - - temp_passback = passed_back.get( "passback" ) - - if temp_passback is not None and len( temp_passback ) > 0: - temp_passback = temp_passback[ len( temp_passback )-1 ] - else: - temp_passback = "( )" - - last_passback = ssxp2hash( string2sxp( temp_passback ) ) #use special function - will work with no head on sxp - - if DEBUG: print last_passback - - for (key, value) in passed_back.items(): - if key not in do_not_parse: - last_passback[ key ] = value[ len( value ) - 1 ] - - self.passback = sxp2string( hash2sxp( last_passback ) ) #store the sxp - - if DEBUG: print self.passback - - def write_BODY( self, request, err ): - - if not self.passback: self.parseForm( request ) - - request.write( "

%s

" % self.title ) - - previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the hash for quick reference - - request.write( "" ) - - for (feild, control) in self.feilds: - control.write_Control( request, previous_values.get( feild ) ) - if err and not control.validate( previous_values.get( feild ) ): - control.write_Help( request ) - - request.write( "
" ) - - request.write( "

" % self.passback ) - request.write( "

" % self.location ) - request.write( "

" % self.location ) - - def addControl( self, control ): - self.feilds.append( [ control.getName(), control ] ) - - def validate( self, request ): - - if not self.passback: self.parseForm( request ) - - check = True - - previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the hash for quick reference - if DEBUG: print previous_values - - for (feild, control) in self.feilds: - if not control.validate( previous_values.get( feild ) ): - check = False - if DEBUG: print "> %s = %s" % (feild, previous_values.get( feild )) - - return check - -class SheetControl( HTMLBase ): - - def __init__( self, reg_exp = ".*" ): - HTMLBase.__init__( self ) - self.name = "" - self.reg_exp = reg_exp - - def write_Control( self, request, persistedValue ): - request.write( "%s" % persistedValue ) - - def write_Help( self, request ): - request.write( "

Text must match pattern:" ) - request.write( " %s

" % self.reg_exp ) - - def validate( self, persistedValue ): - if persistedValue is None: - persistedValue = "" - - return not re.compile( self.reg_exp ).match( persistedValue ) is None - - def getName( self ): - return self.name - - def setName( self, name ): - self.name = name - -class InputControl( SheetControl ): - - def __init__( self, name, defaultValue, humanText, reg_exp = ".*", help_text = "You must enter the appropriate details in this feild." ): - SheetControl.__init__( self, reg_exp ) - self.setName( name ) - - self.defaultValue = defaultValue - self.humanText = humanText - self.help_text = help_text - - def write_Control( self, request, persistedValue ): - if persistedValue is None: - persistedValue = self.defaultValue - - request.write( "

%s

" % (self.humanText, self.getName(), persistedValue) ) - - def write_Help( self, request ): - request.write( "

" ) - request.write( " %s

" % self.help_text ) - -class TextControl( SheetControl ): - - def __init__( self, text ): - SheetControl.__init__( self ) - self.text = text - - def write_Control( self, request, persistedValue ): - request.write( "

%s

" % self.text ) - -class SmallTextControl( SheetControl ): - - def __init__( self, text ): - SheetControl.__init__( self ) - self.text = text - - def write_Control( self, request, persistedValue ): - request.write( "

%s

" % self.text ) - -class ListControl( SheetControl ): - - def __init__( self, name, options, humanText ): - SheetControl.__init__( self ) - self.setName( name ) - self.options = options - self.humanText = humanText - - def write_Control( self, request, persistedValue ): - request.write( "

%s

" % self.humanText ) - request.write( "" ) - - def validate( self, persistedValue ): - for (value, text) in self.options: - if value == persistedValue: - return True - - return False - -class FileControl( InputControl ): - - def __init__( self, name, defaultValue, humanText, reg_exp = ".*", help_text = "You must enter the appropriate details in this feild." ): - InputControl.__init__( self, name, defaultValue, humanText ) - - def validate( self, persistedValue ): - if persistedValue is None: return False - try: - open( persistedValue ) - return True - except IOError, TypeError: - return False - - def write_Help( self, request ): - request.write( "

File does not exist: you must enter a valid, absolute file path.

" ) - -class TickControl( SheetControl ): - - def __init__( self, name, defaultValue, humanText ): - SheetControl.__init__( self ) - self.setName( name ) - self.defaultValue = defaultValue - self.humanText = humanText - - def write_Control( self, request, persistedValue ): - request.write( "

%s

" % self.humanText ) - - if persistedValue == 'True': - request.write( "" % self.getName() ) - else: - request.write( "" % self.getName() ) - - request.write( "" ) - - diff --git a/tools/python/xen/sv/__init__.py b/tools/python/xen/sv/__init__.py deleted file mode 100755 index 8d1c8b69c3..0000000000 --- a/tools/python/xen/sv/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/sv/params.py b/tools/python/xen/sv/params.py deleted file mode 100644 index beed647a4f..0000000000 --- a/tools/python/xen/sv/params.py +++ /dev/null @@ -1,3 +0,0 @@ -SV_PORT = 8080 -SV_ROOT = "/var/lib/xen/sv/" -PID_FILE = "/var/run/xen-sv.pid" diff --git a/tools/python/xen/sv/util.py b/tools/python/xen/sv/util.py deleted file mode 100755 index 3207b8f0cc..0000000000 --- a/tools/python/xen/sv/util.py +++ /dev/null @@ -1,123 +0,0 @@ -from xen.xend.XendClient import server -from xen.xend import sxp -from xen.xend import PrettyPrint - -import types - -def getDomInfoHash( domain ): - domInfoHash = {} - try: - domInfoHash = sxp2hash( server.xend_domain( domain ) ) - domInfoHash['dom'] = domain - except: - domInfoHash['name'] = "Error getting domain details" - return domInfoHash - -def sxp2hash( s ): - sxphash = {} - - for child in sxp.children( s ): - if isinstance( child, types.ListType ) and len( child ) > 1: - if isinstance( child[1], types.ListType ) and len( child ) > 1: - sxphash[ child[0] ] = sxp2hash( child[1] ) - else: - sxphash[ child[0] ] = child[1] - - return sxphash - -def ssxp2hash( s ): - sxphash = {} - - for i in s: - if isinstance( i, types.ListType ) and len( i ) > 1: - sxphash[ i[0] ] = i[1] - - return sxphash - -def hash2sxp( h ): - hashsxp = [] - - for (key, item) in h.items(): - hashsxp.append( [key, item] ) - - return hashsxp - -def string2sxp( string ): - pin = sxp.Parser() - pin.input( string ) - return pin.get_val() - -def sxp2string( sexp ): - return sxp.to_string( sexp ) - -def sxp2prettystring( sxp ): - class tmp: - def __init__( self ): - self.str = "" - def write( self, str ): - self.str = self.str + str - temp = tmp() - PrettyPrint.prettyprint( sxp, out=temp ) - return temp.str - -def getVar( var, request, default=None ): - - arg = request.args.get( var ) - - if arg is None: - return default - else: - return arg[ len( arg )-1 ] - -def bigTimeFormatter( time ): - time = float( time ) - weeks = time // 604800 - remainder = time % 604800 - days = remainder // 86400 - - remainder = remainder % 86400 - - hms = smallTimeFormatter( remainder ) - - return "%d weeks, %d days, %s" % ( weeks, days, hms ) - -def smallTimeFormatter( time ): - time = float( time ) - hours = time // 3600 - remainder = time % 3600 - mins = remainder // 60 - secs = time % 60 - return "%02d:%02d:%04.1f (hh:mm:ss.s)" % ( hours, mins, secs ) - -def stateFormatter( state ): - states = [ 'Running', 'Blocked', 'Paused', 'Shutdown', 'Crashed' ] - - stateStr = "" - - for i in range( len( state ) ): - if state[i] != "-": - stateStr += "%s, " % states[ i ] - - return stateStr + " (%s)" % state - -def memoryFormatter( mem ): - mem = int( mem ) - if mem >= 1024: - mem = float( mem ) / 1024 - return "%3.2fGb" % mem - else: - return "%7dMb" % mem - -def cpuFormatter( mhz ): - mhz = int( mhz ) - if mhz > 1000: - ghz = float( mhz ) / 1000.0 - return "%4.2fGHz" % ghz - else: - return "%4dMHz" % mhz - -def hyperthreadFormatter( threads ): - if int( threads ) > 1: - return "Yes (%d)" % threads - else: - return "No" diff --git a/tools/sv/Main.rpy b/tools/sv/Main.rpy deleted file mode 100755 index 6b75ea9431..0000000000 --- a/tools/sv/Main.rpy +++ /dev/null @@ -1,3 +0,0 @@ -from xen.sv.Main import Main - -resource = Main() diff --git a/tools/sv/Makefile b/tools/sv/Makefile deleted file mode 100755 index 4da91e0674..0000000000 --- a/tools/sv/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -sv_insdir := /var/lib/xen/sv -INSTALL = install -INSTALL_DIR = $(INSTALL) -d -m0755 -INSTALL_DATA = $(INSTALL) -m0644 - -all: - -IMAGES = xen.png orb_01.jpg orb_02.jpg -IMAGES += left-end-highlight.jpg left-end-no-highlight.jpg -IMAGES += right-end-highlight.jpg right-end-no-highlight.jpg -IMAGES += middle-highlight.jpg middle-no-highlight.jpg -IMAGES += seperator.jpg -IMAGES += seperator-left-highlight.jpg seperator-right-highlight.jpg -IMAGES += shutdown.png reboot.png pause.png unpause.png destroy.png -IMAGES += small-destroy.png small-pause.png small-unpause.png -IMAGES += next.png previous.png finish.png - -install: - # copy XenSV Main.rpy file - @[ -d $(DESTDIR)$(sv_insdir) ] || $(INSTALL_DIR) $(DESTDIR)$(sv_insdir) - @$(INSTALL_DATA) Main.rpy $(DESTDIR)$(sv_insdir) - - # copy XenSV images - @[ -d $(DESTDIR)$(sv_insdir)/images ] || \ - $(INSTALL_DIR) $(DESTDIR)$(sv_insdir)/images - @(cd images && $(INSTALL_DATA) $(IMAGES) $(DESTDIR)$(sv_insdir)/images) - - # copy XenSV stylesheet - @[ -d $(DESTDIR)$(sv_insdir)/inc ] || \ - $(INSTALL_DIR) $(DESTDIR)$(sv_insdir)/inc - @$(INSTALL_DATA) inc/style.css inc/script.js $(DESTDIR)$(sv_insdir)/inc - -clean: - diff --git a/tools/sv/images/destroy.png b/tools/sv/images/destroy.png deleted file mode 100644 index 9545fc4837b958ef6e146c2c5f21e30258e8d8ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2408 zcmW+&3pCW(AHTnOV`e-WljqE+)}xY3b*OkTHvM@GUZ7BG^0G0CcHdaRb*QYvXuMV7%Xv1Mx>gW5WS^{}Dkr!|QNp zM7VEw=>DXb*6=L=5WaYMvi%dg1z(qz+|YH3o_j~IaDl$wL__kNw`TF%f@R3V5R|k>+#RL+i|09Q3e`Zp)$g0J4vpJ08|#= zNv@8_$;%Ve$BmMkUf&FPEMR>7cPfO~(A(P^aU5yl`G2tMG!QCNEBh*@^&{oEN4hUc zzC8lGH^v1A2S-Q6#KhPGA2yE9hGI8v{KTR)<6zo`H$)6$!_ay<1CCCfY|f^K4<||~ zil%wP27>`U<AG+%(7q+lK=$sL=B34*( zb@A(b)AY=U4~`%DL{?MNCabE_`c#mWMMN`~;4mWPntcBm(jO<6`ZU9>`Q@r%fFi8S zZb;H7u}04(9-drk^OWn=(oX1I8{z8zyd}F_O<_&_Xq7;usxeg2t4px_y zrTZEp5G+d`(W$;F9JApO;hAOf_^^)Gukp=#Ez4x?Xv#6xf^kjABeJ(6zx~~5dm~kC zSo1nz6GTQxpk?dPOmj=Qc;K9!b)6Gj^sckQV z>ykJP54Pr8VZwB%!HNoV?>r2FVOe&(Jo@wWpjl9owtu5|hAhw3`DA3>#Ui^M{l~27 z%C>ApE%v#?fC`<2^N)s^wIl*R>oo}52`TXeMtw7EVd#17F1^JM0gkV0vwC%^=H*|% zZ7^=Tbo1Aoge?XN$!j} zdj`>4T0UKV4b45sFi|~)j^*^y@XWs@P`*>8>7PK4wWH(Cly;Ww;h;pRL?U7D*pbB! z2%t{#c^1&*dwARecTf}?3RG5ExK02)!Pt^YB7Z`quKvZ@*%?Qp(W2QgQ++PdJX8Io z!>CLg5<7oAW#fr2@r)ZYRO`DeTOFPO+R#8|kR4E(>NFY%CtLz7Pz!ABQRlY~y~;G_ zc~Je+o4ONa$%J8hUX)mhi22g8y~q8ADg1MWI6c-{7Jh8EK-+ps7#S&!%-I$VW# zVhqRb;1upH2s2ro6<%i#@ElsYyG?rkX5iqU4~Uiqx|E$)wi%bYp73_ah9=y(h;@kK z<0nz)d6&zCuR1%Sx^_jvvMS(je@G~V_gcubivwEq8E_z6y29q9SfE82FF>taxiZ=Z zqneX(YL}3w3gL`c{cAy7ZuaWZREQ@z93IX&otF!J-zi_Q*h!R~dyZK`252MJr$}Vps!1#R1^eCaCU9mAdv3fH2p6 zic<9Q_X$ZX+LZt)DAp`Tf}|~EarGj8q;s)&JpSz#+<1bwoyZ51 z$t|C=kARF|*hB>R_3QH46coY?sZ>gb6I#so%@g}EP#sj+z7;!-RTaxS=#9h$Q{f|A@Pr zhQ=+DoSlD9V7juvW0wO0!3?nOOt&pb+j=PS=S&zig;)or2%1!AFDxv$!5@(%hffA? z-Fm=Y7-inTfF!G0;_jgK+ziHM2j}YaH5|L=&1OU8Q)nbuVM8}}e0;n{@rTIN#Va-A zN>vV?354D1&mZ3v`0L*k-?(}jF-mJJ1~IiAU!6B^o`OVvmQen1$n5Z~xY1qJlvXA% zx!wQp#OA&tA9tWqB$kwx_GPRi>#+hOer#%NtN=ZkZ`DP{1?^ooLv(5MG76m6cRyjm zy4p&NRc1_1MqT&N04P0<9OUPB`*cakH=QrQs#4uwAG5Nl+~-0IEgjnFeLc9L__7Lr zKg>!lZFJ5>fJ(gJG1+sEJA@RIcDB9bFq7inQCL(Y#)oH)txBD-uADtKH*UzO{Wh-| ztz&UV(lauK_K_hy7G}8|XwD71eQ>lN(loj8Crl3!(<~d=%XDA7c)@RPRNAr1*9fZ# z!}=Y)%gYU2T5hn8MuGEvUi$j_iKhyXYNGyOn?pp~MVrBuID}g|(aP|`lUEsK8&9lzch?; zcc&`XlU>g2@K`RUeIZP~ZML$sbY(P~!QgV@*jo9zAv~2_qu6wl8fX=R>WQkBHDd0z zoGvVce(F%T54y_j5+HRED$`KkW_*RmVu diff --git a/tools/sv/images/finish.png b/tools/sv/images/finish.png deleted file mode 100644 index 6c5d18a9b7f6091f3a92723f27029b7629ee45e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1189 zcmV;W1X}xvP)?bz6rVnQ>h|v4JG-}U-)epM@Im_j|Nm@2<-fSN zxL%5ji(h7CWj&^(q_iEV{_fwue;Gc1{>mdTuC87O^zkGhX88U4H(U)s z0HIh03=SrsZ#s@0J5~yFG0X=rOOV;v04NwiKvh+BmYJDZKG2~*U}69P!~#nx!vO+_3FH!>HHYHMixEHo zvAlo(UW%9$2ueJ1a&io6YHAF8e0*TTK|Tce4(3Aw!TBE`fS7=qm3f($%7 zJYbiCLIdPe5JoNl@Bx4T0$KK-7=@rB2jm0fvJT`MVC2J#D0~2D&0l~3Vgd%mGh*xm z8T|P1V=(^u^(!b2!149``EwKp;0sBB0Adjq7QPIuLbM5GXprk)y?O=q9k3Vzm-4_Y z15O+uHWB&lEkFRVaB^~90@6zy!qrbR4`|A;uz5))EpDS_=?BOu$HA1FT_x z5E*swdJBY!u?Xs`Z@`e-0}w!z+BPf&h0F(1i zbl(x{TLPB726|>T$R2i9B06IPgm=1o!%mB#)1P~K?f&eP~2W*b@0rQ0mP{9_UtG4m{ftLCLgH#iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%dekC{=Bfk}{&S&;Gn5r%38 zMn*=UBM|`TNT3K4GeU%cffeXqW)=YkMrI}^R$jPzW=19!238?9K|^8DsfvM(7o8?4 z2VcGtDi+2r2vp0=!pI6Y1!SaPppc?tknqNd3zdpQ{@-HYVFro{G7B=;Gu*x%&24aJ z{ie@464!IYg^#sx9!zOuGAYkFcCn}9nQ1uJ&QqOBLrY&R_pvaXAtiLdS1)k?is=>+ z7nQ&IKi@xj(}x%H<|ap4T3=cH-u+hY(vq3)rSDv+*}OAw)yh*#%T3GO9$q{3QBH6Z z^Nsf#KTW*I-%->mf}ZR|TF=ZWX7ykGQCvS@G=A<(n@T pNxa-3mAT2O%q6Za#QMd`dy>r$lM2~?d(AwZx_X^m-O>90HvxDKkz4=( diff --git a/tools/sv/images/left-end-no-highlight.jpg b/tools/sv/images/left-end-no-highlight.jpg deleted file mode 100644 index ded4e3933b1550e8bd4342151fb9061d5b8de551..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 440 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%dekC{=Bfk}{&S&;Gn5r$L- zMn*=UBN2d=g&j=G!GHO}Nr!@1L!69byZ1~lW!ii6-p-=+whU#iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%dejhRu9fk}{&S&;Gn5rzx~ z24W#d-)bK*SdomkC*SPmwEWNTIUCU@j W9iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%deotaUPfk}{&S&;Gn5r!BB zMn<3;kpK$^x(EY<00RRPJ13GN2F8gOnSz*E*e;1oxgr`mRV+*p%@|-X++yHiW&~Qr nEXZKbu+ZwM?xquo2{##T_k`c_T*FXW_5JM0Pw7(`|K9`vAj&v0 diff --git a/tools/sv/images/next.png b/tools/sv/images/next.png deleted file mode 100644 index da10bbfb9b48eeebdfdebea4c05bd29648fed054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1270 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�P;-LL5O1CHK1w@JGP!n}1tVr#=+19bFChk&0vg7~%pJE=Onn51Ks+ zx-kJ zkD9tX{8!WZ=MjE^93TecF94^=wI48srxO~_y7>sE^=?Cy7v;JWJnK|{>Go?5TuPN& zzcpDfl0)Z=v;C2wSpV!X{n>>6rDOFUciWZA+aAoCBM5T9gA&o1tlVxt>#Tr8A6=PW zQT(+ac(Gk2J2L5me7fyXQ(b`SuMPic0nCL5(2RrQZZUtCRQP10INQz0#xt2>4GaJ2 zyMEK3`OV(E+Pm%gVACLD$tOP!R8Hq8S@T}mV-?+5*+<4;AV2|v4-96dXJgJNs5 z(*FlWg{ioj-`nmRuF6XM?u0JC%mEgOar4>gS)xlkGP ztB253Vf`1QuFWNkYBI=y_(~4&|H6p={rCT2Foxn#mCLc_a{ay;)Gzt&t5go&c%9p- z{)eIdpXy?5Riv7@1DylTZoBx1&yxJr2@GdAfppvcvmgIVb@YlhL;sdU7B6P9V^q}- z{XfO!cY^^>bJ(k5r!M{Yodgqq7cqTdn%wv(|Cubi1C!xTh6|XxSM|SJ0rD6D@md(* zcj@HxNvp3qxl3pCZ2o_ft3qI4mM=5%>hAAH%f*ari_$H{T;lw{@G1XoIsi`tJvESq z$G=n9b^r`%Lno4LU8UOoEQ{X{*-Z^)i36!-BTl{gR}Z6Q87Hcr^g%(V(Z>7-RiR`5 zJ!*h1!Egt5ckKEuL&di*ZZwZ%$DhAubpPS0hrs_HTDyWES9c42CyQL=VbQ#!9~8V6 zpWX`ki*>~BR~7%28c@iRalY|8Y(3w;*wM>t(vkfaj@qA9{Wnql)#dx0R{Bop0p`bm z@6ubflLG24u@~lGjn*&X|2+=zw;~U!RX+^)E<<}k>EyeJMLYgR+>^R1|5YNeffy_D z@A69SwxJ&mo^b2WVW9N4pZHx3-=**N?Z5I(t$3#y@BKMg^<9JiMW_FW};Fre=z!Abp8MN2LSvsW&Xd&zrdaD{{vbYa~J>s diff --git a/tools/sv/images/orb_02.jpg b/tools/sv/images/orb_02.jpg deleted file mode 100755 index e5ebc8e4b14f12336539140b8ae82dfc9fefcc7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 507 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgMpKohnZ23fk}{&S&;Gn5r$|6 zMi2lx6AoAznK;mdfO1R%j0}v-tZ-F8h7ltZ%O>Vx6IMZVBN!MRnf~8m09pmKiCK`r zp5d$68xN%?`MFg*dntcRN{P`o7ug&RVg@ c>y-$aDklEPT>49n-d1WgL6ael%l`i+06=m-0RR91 diff --git a/tools/sv/images/pause.png b/tools/sv/images/pause.png deleted file mode 100644 index 6e16daa177a47f3cf58fc0dc83bea2f2cba888c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1662 zcmV-^27&pBP)VzaL`3A0 zva<3i4i1h>K=E_J!onY@xpwqyUVCptEPs#@xDf%aDPJ02qU>9334yg@lCG z0X_JD95Vm{h-8lelN%q9iamDhSkB|ek2M%*2pAa||G2uk76=LoE(RvkPo(Gt2q2O? z2K1B*&@&l8PX#m35ddTGp_i9eiiCv39%A(X1Q5|4117zkO`A3~e*XMfh+%+$ySsZX zu&|jzj9P#IBIq%ohXjEoTiM2q8!H$F0g#uMUu$@A0Vv2q3&3113F*4TN6!)F+eMg?*g)t4 znsHu9NeQJY00~`?%b&X#+m|*4-i0bkNy1lGld+Q0I;j&4-i01z-ZGPZXWyk^{Xd905M&^e%+Q~_yI6E83CrQzl) zV2m9B2p}dlHnwv>#;{3?z|{9cS64R#Ab^+@6%{|Qva;S8M)~ZEm6g>8fB*vbpn*QD z8ZH$zu$1Qp(EtGi_LzWxz-|^6mLcycVB~zz*4CB;u>k@I>@f`ujgLx7O2wZ(eH!Y1 zYqqzy2T#fa1Q2{&QA9*!9S;xBtD&0LfZeYfa&mI(V0?f8f_u!w#N+``q6yfo9+Dp8 z;^Gqa_xFDQ;{yZ`%GkY(jLc$Seq$JF17)c5HP8gRrnLzSrHo00aFdAvHm_gJ6nku^#B1x(ju`{t5&%@fBt+b zFyEbP%0BV6P7EWNBO%+u4fjmi!M?v=g{{0(N zINb-h5I~I7Y&xx9zg_@Xp&9{0Tn|`Bg?;(*2~5JTfdTLq*rU(~20${fje0IBDvD~0odE(206x2i9mk?v%K!iX07*qo IM6N<$f|-xg+W-In diff --git a/tools/sv/images/previous.png b/tools/sv/images/previous.png deleted file mode 100644 index 22292d6e9c8d7aa0c3ee21d9dfa96988178837c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1285 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 diff --git a/tools/sv/images/right-end-no-highlight.jpg b/tools/sv/images/right-end-no-highlight.jpg deleted file mode 100644 index 0ddd058d6709f02c30724843e5748aad0beda086..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%depP5mRfk}{&S&;Gn5rzx~ z1}0{pBN2cZ=t>SoMuY%_CBVSQ%*e{j3zuMIVrF4w5Ofq`Q#71-QOPLilCa2>E25!O z#li&PieRSvzs11A%m}oWS&+e=;llhmm+o^jpW1wLgU)=W`AqA5T_k#rx10L8uW-rS zvUK|F;FO-XjT7!H-1qiKPmUNr)BD&Mf8EB=D5=Rtj4D&hUvjEE%9pmd!T;{p_n$lJ v(`t2_M2>Ie-u&?7%47Yq*QPD@UvBhj4&RAWMeQjm&$=6Bc?xeP{J#kR!QN$y diff --git a/tools/sv/images/seperator-left-highlight.jpg b/tools/sv/images/seperator-left-highlight.jpg deleted file mode 100644 index c90f4ffd12e68734418ca4a6199400fcdbfb391e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 552 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%czoS9LOfk}{&S&;Gn5r#Sj zMj!yX5)Rl{S=iCV7+6@@1Q-}tSQt6D;ffiVm{}MES=mGlCteh~5;|2(F)%S`(xu?b zB2&WHfmSduvvR@}1A{@3Nl4K!keS6Xv9NLC!60GQh5v6c@Gvt19m6chV9)SUX62vn zpGx9nF5m7hJo9PxYW3>VVoSHDPJR5yY$YsWHbBqq`f8 zUv9aw;r@-qpBGE+EEoMFTK(*tRg$NVct?!%)a3$pCq-7DJ<$95^yfcmuT;I>C{K5~ z)N(PnQ;3zjW5%upOv_fBiTZLbc^3bQ;vFFijNNrs?uyB~d1Pbv{r$7kj~q{J>b3uW F69CD!m}39{ diff --git a/tools/sv/images/seperator-right-highlight.jpg b/tools/sv/images/seperator-right-highlight.jpg deleted file mode 100644 index f37e6cd546960f837682c31793c3ab70a9e41e36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 560 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%czoS9LOfk}{&S&;Gn5r$?4 z1}0{pBN2d=jfI_q5nYspm4TT}fPsO9nVEx|5vH1viJ66gl}%7l^rEoHmC&hTVS$Mg zm4YT+at^*cg@d~9pkNYI6k-l63=(E>Oq{rI<3Xh+*8jH{c$k6q2{H>Z z*fU(1W9gj}CO=i)$BC;{*3?C=OtskeRE)&hNkTKjbo&&T7Hwyk(R`7oV(LZJkom4B zg#O-&8yk=90XieH%nGF+?RIds>XIsIeu<(G13)5qc z>h99R`_F~F^$+@`Fn_-6`SrV+3y#NY%}Y*gUX{mCe5B&&>wD4Zdya?pY+S;4HqF#= zSyH-@S?BthKE@TD$9J#?9o!;yv!dhRG?_2?N0lau7tJ_YbC)x5rntZgGi~1owLyC8 O-ZA_x`}$M!|4jhxDU(tF diff --git a/tools/sv/images/seperator.jpg b/tools/sv/images/seperator.jpg deleted file mode 100644 index c77e2c5500d19b598c419901916feb9b65c20ce5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 443 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%czoS9LOfk}{&S&;Gn5r#Ad zMn*=UBN2d^g#%3lC?~+cz|6|b%?ek>$i&Pb$RffvF-TO=G4bN1DOWKdsQf5I0dxi^hcX}5^@LrXj#-M8JJP(1qjzI5}e0Cz>y>E3XFXZYu1(b_V9OK-)GK#<#=nt|C<1QXkmH) diff --git a/tools/sv/images/shutdown.png b/tools/sv/images/shutdown.png deleted file mode 100755 index 48a52dce217ebe0e3e3d5c148bb1bfcfa2a7fd88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2901 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 feXAVM7;V6O*9ZG8z{!&*89*9A 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 diff --git a/tools/sv/images/xen.png b/tools/sv/images/xen.png deleted file mode 100644 index 344c361b3cc1182bf22ab1da590936157f8e851d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10575 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